<?php
//$columnModel = $this->getColumnModel( $grid_name );
/*
 * Можно создать гриду с именем new GridWrapper( $grid_name = "photo_plitka"),
 * а можно пустую и потом засетапить опции: $grid->set($data, $name)
 *
 * Имя гриды photo_plitka совпадает с именем xml-файла
 *
 */
/* EXAMPLES
 * $zones_grid->set_navigation(array(
                    'view' => true ,
                    'search' => false ,
                    'edit' => true ,
                    'add' => true ,
                    'del' => true
                ));
$zones_grid->set_edit_options(array(
                    'msg' => 'Error' ,
                    'width' => 460
                ));
 */
/*
 * TRASH
 *
 * function _getGridModel($modul = null, $filename, $root = null){

       $modul = Registry::getInstance()->modul_index;

       $data = $this->model->getColModel($modul, $filename, $root);

       if(isset($data[$filename . '_grid'])){
           return $data[$filename . '_grid'];
       }
       else return $data;

   }*/

class GridWrapper /*extends jqGridRender*/
{

    private $grid_name = '';
    private $grid_unit = '';
    private $modul = '';
    private $root = null;
    private $grid_model = null;
    private $column_model = null;
    private $grid_html = '';
    private $nav_config = null;

    private $jsonReader = array("root" => "rows", "page" => "page", "total" => "total", "records" => "records", "repeatitems" => true, "cell" => "cell", "id" => "id", "userdata" => "userdata", "subgrid" => array("root" => "rows", "repeatitems" => true, "cell" => "cell"));

    protected static $config_options = array('viewrecords' => true, 'recordtext' => 'Records', 'rowList' => array(10, 15, 20), 'datatype' => 'json', 'loadui' => 'block', 'hoverrows' => true, 'resizable' => true, 'loadtext' => 'Loading...', 'rowNum' => '15', 'forceFit' => true, 'sortname' => false, 'sortorder' => 'desc', 'width' => '100%', 'hidegrid' => false, 'height' => '100%', 'auto', 'caption' => ' List');

    protected static $nav_options = array('edit' => false, 'add' => false, 'del' => false, 'search' => false);

    protected $_config;
    protected $_subgrid;
    protected $event = false;

    protected $view = null;

    /**
     * jQuery selector. Special for Grid
     *
     * @var unknown_type
     */
    protected $_gridSelector = '#list';
    /**
     * jQuery Pager. Special for Grid
     *
     * @var unknown_type
     */
    protected $_gridPager = 'pager';
    protected $_imagepath = 'images/';
    /**
     * An associative array of files to include into HTML
     *
     * @var assoc array
     */
    protected $_files = array('base' => 'grid/jquery.jqGrid.js');
    /**
     * Path to Grid themes
     *
     * @var string
     */
    protected $_themesPath = 'grid/themes/';
    /**
     * Current Grid theme name
     *
     * @var string
     */
    protected $_theme = 'basic';
    /**
     * Navigation Buttons
     *
     * @var string
     */
    protected $_navigation = '';
    /**
     * Form Editing Options
     *
     * @var string
     */
    protected $_form_edit_options = array('addCaption' => 'Add Record', 'editCaption' => 'Edit Record', 'bSubmit' => 'Submit', 'bCancel' => 'Cancel', 'bClose' => 'Close', 'saveData' => 'Data has been changed! Save changes?', 'bYes ' => 'Yes', 'bNo ' => 'No', 'bExit ' => 'Cancel', 'closeAfterAdd' => true, 'closeAfterEdit' => true);
    protected $_form_edit_enabled = false;
    protected $_form_edit = '';
    /**
     * Current Grid Url
     *
     * @var string
     */
    protected $_url;
    /**
     * Current Grid Method(POST/GET)
     *
     * @var string
     */
    protected $_method = 'POST';
    /**
     * Current Grid datatype
     *
     * @var string
     */
    protected $_datatype = 'json';
    /**
     * Current Grid columnnames
     *
     * @var assoc array
     */
    protected $_columnnames;
    /**
     * Current Grid colummodels
     *
     * @var assoc array
     */
    protected $_columnmodels;

    /*
     * $grid_name: plitka
     * $grid_unit: plitka_grid
     * $pager: plitka_pager
     */
    function __construct($grid_name = null, $modul = null, array $config = null)
    {


        $this->setConfig($config);

        if (!is_null($grid_name)) {

            $grid_name_cutted = preg_replace('/_grid/','',$grid_name);

            if( $grid_name !== $grid_name_cutted){
            // В качестве имени передано имя с приставкой _grid
                $this->grid_name = $grid_name;
                $this->grid_unit = substr($grid_name,0,-5);
            } else {
            // В качестве имени передано имя без приставки _grid
                $this->grid_unit = $grid_name;
                $this->grid_name = $this->grid_unit . "_grid";
            }

            $this->setGridSelector('#' . $this->grid_name);
            $this->setPager($this->grid_unit . '_pager');
        }

        if (!is_null($modul))
            $this->modul = $modul; else
            $this->modul = Registry::getInstance()->modul_index;

        $this->view = Registry::getInstance()->modul_view;

        $this->init();

        try {
            if (!is_null($grid_name)) {
                $this->grid_model = $this->getGridModel();

                // Мои методы не используются, но переход на них возможен
                //$this->grid_options = $this->getGridConfig();

                //$this->column_model = $this->getColumnModel();

                $this->_setGridParamsXML();

                $this->_setColumnModels();

            }

        } catch (Exception $e) {
            fb($e->getMessage());
        }

        return $this;
    }

    function setModul($name)
    {
        $this->modul = $name;
    }

    function setGridName($name)
    {
        $this->grid_name = $name;
    }

    function setRoot($name)
    {
        $this->root = $name;
    }

    function init(){
        if (!isset($this->grid_options['caption']))
            $this->setGridParam('caption', '');
        if (!isset($this->grid_options['rowNum']))
            $this->setGridParam('rowNum', 10);
        if (!isset($this->grid_options['sortname']))
            $this->setGridParam('sortname', '');
        if (!isset($this->grid_options['hoverrows']))
            $this->setGridParam('hoverrows', true);
        if (!isset($this->grid_options['datatype']))
            $this->setGridParam('datatype', 'json');
        if (!isset($this->grid_options['mtype']))
            $this->setGridParam('mtype', 'GET');
        if (!isset($this->grid_options['rowList']))
            $this->setGridParam('rowList', array(10, 20, 50));
        if (!isset($this->grid_options['gridComplete']))
            $this->setGridParam('gridComplete', 'function(){}');

        if (!isset($this->grid_options['url']))
            $this->setGridParam('url', '');
        if (!isset($this->grid_options['editurl']))
            $this->setGridParam('editurl', PUBLIC_URL);

        if (!isset($this->grid_options['jsonReader']))
            $this->setGridParam('jsonReader', $this->jsonReader);
    }

    /*
     * Sets the class configuration
     * @param array $config
     */
    public function setConfig($config = null)
    {
        if (!is_array($config)) {
            $this->_config = self::$config_options;
        } else {
            $this->_config = $config;
        }
        return $this;
    }

    public function setPager ($pager)
    {
        return $this->_config['pager'] = ($pager != '' ? $pager : $this->_gridPager);
    }

    /*
     * Sets the grid selector class or id
     * @param string $selector
     */
    public function setGridSelector($selector)
    {
        if ($selector !== '')
            $this->_gridSelector = $selector;
        return $this;
    }

    public function _setGridParamsXML(){
        $config = $this->getColModel();

        if(isset($config[$this->grid_name]['config']))
            $config = $config[$this->grid_name]['config'];

        $this->setGridParamsXML($config);
    }

    public function setGridParamsXML($config)
    {

        if(!isset($config['values'])) return false;

        foreach ($config['values'] as $values)
        {
            switch ($values['type'])
            {
                case 'subarray':
                    $setting = array();
                    foreach ($values['param'] as $param) {
                        $setting[$param['name']] = $param['setting'];

                        if ($param['type'] == 'str') {
                            $setting[$param['name']] = $param['setting'];
                        } else {
                            $setting[$param['name']] = array($param['setting']);
                        }

                    }
                    break;
                case 'str':
                    $setting = $values['setting'];
                    break;
                case 'array':
                    $setting = preg_split('/:/', $values['setting']);
                    break;
                case 'translate' :
                    $setting = $values['setting']; //$this->view->translate($values['setting']);
                    break;
            }

            $this->setGridParameter($values['name'], $setting);
        }
    }

    public function setGridParameter ($parameter, $value)
    {
        return $this->_config[$parameter] = $value;
    }

    function _setColumnModels(){

        $colummodels = $this->getColModel();

        if(isset($colummodels[$this->grid_name]['column']))
            $colummodels = $colummodels[$this->grid_name]['column'];

        $this->setColumnModels($colummodels);
    }

    /*
     * Sets Column Models for the Grid
     *
     * @param array $colummodels
     */
    public function setColumnModels ( $colummodels = null, $column_model_changes = null)
    {

        if(!is_array($colummodels)) return false;

        $column = array();
        $tmp_column_models = array();
        foreach ($colummodels as $key => $GridColumn) {

            //if ($this->acl->checkColumn($GridColumn)) {

            /*
            if($GridColumn['name'] == 'link'){
                fb($colummodels);
            }
            */

                if (isset($GridColumn['title'])) {
                    $column[] = $GridColumn['title'];//$this->view->translate($GridColumn['title']);//
                } else {
                    $column[] = $GridColumn['name'];//$this->view->translate($GridColumn['name']);//$view->translate('column_' . );
                }
                if (! is_null($column_model_changes)) {
                    foreach ($column_model_changes as $key_ch => $single_change) {
                        if ($key_ch == $GridColumn['name']) {
                            $GridColumn[$single_change['path'][0]][$single_change['path'][1]] = $single_change['value'];
                        }
                    }
                }
                $tmp_column_models[] = $GridColumn;

            //}
        }

        $this->_columnmodels = $tmp_column_models;
        $this->_columnnames = $column;
        $this->_config['colNames'] = $this->_columnnames;
        $this->_config['colModel'] = $this->_columnmodels;
        return $this;
    }

    /*
     * Sets the Url configuration
     *
     * @param array $config
     * @return Fooup_jQuery_Grid
     */
    public function _setUrl ($url)
    {
        $this->_url = $url;
        $this->_config['url'] =  $this->_url;
        return $this;
    }

    /*
     * ========================================================
     */

    function getColModel($modul = null, $filename = null, $root = null)
    {

        if (is_null($modul))
            $modul = $this->modul;
        if (is_null($filename))
            $filename = $this->grid_name;
        if (is_null($root))
            if (!is_null($this->root))
                $root = $this->root;

        if ((string)$filename == '')
            return false;

        $reader = new Zend\Config\Reader\Xml();

        if(is_file(SITE . "/Moduls/$modul/$filename.xml")){
            $data = $reader->fromFile(SITE . "/Moduls/$modul/$filename.xml");
        } elseif(is_file(SITE . "/Moduls/$modul/{$this->grid_unit}.xml")){
            $data = $reader->fromFile(SITE . "/Moduls/$modul/{$this->grid_unit}.xml");
        } elseif(is_file(SITE . "/Moduls/$modul/{$this->grid_name}.xml")){
            $data = $reader->fromFile(SITE . "/Moduls/$modul/{$this->grid_name}.xml");
        } else {
            $data = false;
        }


        if (!is_null($root)) {
            if (isset($data[$root]))
                $data = $data[$root];
            elseif(isset($data[$filename][$root]))
                $data = $data[$filename][$root];
            elseif(isset($data[$this->grid_name][$root]))
                $data = $data[$this->grid_name][$root];

        }

        unset ($reader);

        return $data;

    }

    function getGridModel($modul = null, $filename = null, $root = null)
    {
        if (is_null($modul))
            $modul = $this->modul;
        if (is_null($filename))
            $filename = $this->grid_name;
        if (is_null($root))
            if (!is_null($this->root))
                $root = $this->root;

        $data = $this->getColModel($modul, $filename, $root);

        if (isset($data[$filename . '_grid'])) {
            return $data[$filename . '_grid'];
        } elseif (isset($data[$filename]))
            return $data[$filename];
        elseif (isset($data[$this->grid_unit]))
            return $data[$this->grid_unit];

        return $data;
    }


    /*
     * Перед использованием метода нужно засетапить название гриды, модуль и корневой элемент
     */
    function setGridColModel()
    {
        // попытаться взять модель из xml
        $this->column_model = $this->getColumnModel();
    }

    /*
    * Перед использованием метода нужно засетапить название гриды, модуль и корневой элемент
    */
    function setGridConfigOptions()
    {
        // попытаться взять конфиг из xml
        $this->grid_options = $this->getGridConfig();
    }

    function getColumnModel($modul = null, $filename = null, $root = null)
    {

        if (is_null($modul))
            $modul = $this->modul;
        if (is_null($filename))
            $filename = $this->grid_name;
        if (is_null($root))
            if (!is_null($this->root))
                $root = $this->root;

        if ($this->grid_model === null)
            $this->grid_model = $this->getColModel($modul, $filename, null);


        $data = false;

        if (isset($this->grid_model['column'])) $data = $this->grid_model['column'];
        elseif(isset($this->grid_model[$filename]['column'])) $data = $this->grid_model[$filename]['column'];
        elseif(isset($this->grid_model[$this->grid_unit]['column'])) $data = $this->grid_model[$this->grid_unit]['column'];
        elseif(isset($this->grid_model[$this->grid_name]['column'])) $data = $this->grid_model[$this->grid_name]['column'];

        return $data;
    }

    function getGridConfig($modul = null, $filename = null, $root = null)
    {

        if (is_null($modul))
            $modul = $this->modul;
        if (is_null($filename))
            $filename = $this->grid_name;
        if (is_null($root))
            if (!is_null($this->root))
                $root = $this->root;

        if ($this->grid_model === null)
            $this->grid_model = $this->getColModel($filename, $root);

        if (isset($this->grid_model['config']['values']))
            return $this->gridOptionsProcess($this->grid_model['config']['values']); else {
            if (isset($this->grid_model['config']))
                return $this->grid_model['config']; else
                return $this->grid_model;
        }
    }

    function setGridParam($key, $value)
    {
        $this->grid_options[$key] = $value;
    }

    function setGridParams($data)
    {

        foreach ($data as $k => $v) {
            $this->setGridParam($k, $v);
        }

    }

    function setGridColumnModel(array $data)
    {
        foreach ($data as $k => $v) {
            $this->column_model[$k] = $v;
        }
    }

    function setNavigatorConfig(array $options){
        foreach($options as $k => $v){
            $this->nav_config[$v] = true;
        }
    }

    /*
     * Роутер опций гриды:
     * - column model
     * - config options
     * - class params
     */
    function set(array $data, $grid_name = null)
    {

        if (!is_null($grid_name))
            $this->grid_name = $grid_name;

        foreach ($data as $k => $v) {
            if ($k == 'navigator')
                $this->navigator = $v; elseif ($k == 'debug')
                $this->debug = $v;
            elseif ($k == 'column_model')
                $this->setGridColumnModel($v);
            elseif ($k == 'grid_config')
                $this->setGridParams($v);
            elseif ($k == 'url')
                $this->_setUrl($v);
            elseif ($k == 'navoptions')
                $this->setNavigatorConfig($v);
            else {
                $this->setGridParam($k, $v); // my variant
                $this->setGridParameter($k, $v);
            }
        }

    }

    function getHtml()
    {
        return $this->grid_html;
    }


    function gridOptionsProcess($grid_options)
    {

        $options = array();

        foreach ($grid_options as $key => $value) {

            $name = $value['name'];


            if ($value['name'] == 'rowList') {

                if ($value['type'] == 'array') {
                    //$setting = preg_split('/:/', $values['setting']);
                    $t = array();
                    $tt = explode(':', $value['setting']);
                    foreach ($tt as $k => $v) {
                        $t[] = $v;
                    }
                }
                $options[$value['name']] = $t;
            } else {
                $options[$value['name']] = $value['setting'];
            }
        }

        return $options;
    }

    public function _setMethod ()
    {
        return $this->_config['mtype'] = $this->_method;
    }

    /*
     * @return string
     */
    public function get_navigation ()
    {
        return $this->_navigation;
    }

    /*
     * Gets the grid selector
     *
     * @return string
     */
    public function _getGridSelector ()
    {
        return $this->_gridSelector;
    }

    public function arrayMergeRecursive($ar1 = array(), $ar2 = array())
    {
        if (!is_array($ar1)) {
            $ar1 = array();
        }
        if (!is_array($ar2)) {
            $ar2 = array();
        }
        foreach ($ar2 as $key => $val) {
            if (is_array($val)) {
                if (!isset($ar1[$key])) {
                    $ar1[$key] = array();
                }
                $ar1[$key] = $this->arrayMergeRecursive($ar1[$key], $val);
            } else {
                $ar1[$key] = $val;
            }
        }
        return $ar1;
    }

    /*
     * @param array $_navigation
     */
    public function set_navigation ($_navigation = array(), $api_fucntion = 'navGrid', $action = 'columnChooser')
    {
        if ($this->_navigation == '') {

            /*
            if(is_null($this->nav_config)){
                $_navigation = $this->arrayMergeRecursive(self::$nav_options, $_navigation);
            } else {
                $_navigation = $this->nav_config;
            }*/
            $_navigation = $this->nav_config;
            $_navigation = $this->arrayMergeRecursive(self::$nav_options, $_navigation);

            $this->_navigation = 'jQuery("' . $this->_getGridSelector () . '").jqGrid(\'' . $api_fucntion . '\',\'#' . $this->_config ['pager'] . '\',' . Controller::encodeJson ( $_navigation ) . ');';
            if ($action == 'columnChooser') {
                //FIXME выдает ошибку TypeError: $.widget is not a function. Возможно, дело в последовательности подклчения или нуже еще файл
                Controller::appendHeadLink(PUBLIC_URL . "/css/ui.multiselect.css");
                //Controller::appendHeadScript(PUBLIC_URL . "/js/ui.multiselect.js");
            }
        }
    }

    /**
     * Gets themes path
     *
     * @return string
     */
    public function getThemesPath ()
    {
        return $this->_themesPath;
    }


    /**
     * Gets the current theme name
     *
     * @return string
     */
    public function getTheme ()
    {
        return $this->_theme;
    }

    public function _setImagePath ()
    { //TODO
        return $this->_config['imgpath'] = "http://" . $_SERVER['HTTP_HOST'] . rtrim(dirname($_SERVER['SCRIPT_NAME']), '/') . $this->getThemesPath() . $this->getTheme() . '/images';
    }

    /**
     * Gets the class configuration
     *
     * @return array
     */
    public function _getConfig ()
    {
        return $this->_config;
    }

    public function set_edit_options ($_edit_options)
    {
        $this->_form_edit = 'jQuery.jgrid.edit = ';
        $this->_form_edit_enabled = true;
        foreach ($_edit_options as $option => $value) {
            $this->_form_edit_options[$option] = $value;
        }
        //$this->_form_edit .= ZendX_JQuery::encodeJson($this->_form_edit_options);
        $this->_form_edit .= json_encode($this->_form_edit_options);
    }

    public function _populate($view = null)    {

        if(is_null($view)) $view = $this->view;

        Controller::appendHeadLink(PUBLIC_URL . "/css/ui.jqgrid.css");
        Controller::appendHeadLink(PUBLIC_URL . "/css/grid_flow.css");
        Controller::appendHeadScript(PUBLIC_URL . "/js/grid.locale-ru.js");
        Controller::appendHeadScript(PUBLIC_URL . "/js/jquery.jqGrid.min.js");

        //TODO что из этих файлов нужно?
        //Controller::appendHeadScript(PUBLIC_URL . "/js/jquery.fmatter.js");
        //Controller::appendHeadScript(PUBLIC_URL . "/js/grid.formedit.js");
        //Controller::appendHeadScript(PUBLIC_URL . "/js/grid.inlinedit.js");
        //Controller::appendHeadScript(PUBLIC_URL . "/js/grid.custom.js");

        /*
         *
        $view->headScript()->appendFile($view->baseUrl() . 'js/grid/js/i18n/grid.locale-en.js');
        $view->headScript()->appendFile($view->baseUrl() . 'js/grid/js/jquery.jqGrid.min.js');
        $view->headScript()->appendFile($view->baseUrl() . 'erp/admin/jgridformatters.js');
        $view->headLink()->appendStylesheet($view->baseUrl() . 'js/grid/css/ui.jqgrid.css');
        */

        $this->_setMethod();
        $this->set_navigation();//columnChooser
        $this->_setImagePath();
        $config = $this->_getConfig();
        //fb($config);
        //fb($config);
        //fb($this->grid_options);
        //$config = $this->grid_options;
        //$config = array_merge($this->column_model, $this->grid_options);
        //fb($config);

        $json = Controller::encodeJson($config);
        $grid_onload = '';



        //FIXME Костыль для устранения кавычек из js-кода
        $json = str_replace('"imageValue"',"imageValue",$json);
        $json = str_replace('"imageElem"',"imageElem",$json);

        //custom_value
        //custom_element



        //Controller::appendHeadCode($grid_onload);

        $grid_onload = 'jQuery("' . $this->_getGridSelector() . '").jqGrid(' . str_replace(array(
                '"true"' ,
                '"false"'
            ), array(
                'true' ,
                'false'
            ), $json) . ');' . $this->get_navigation() . ';';

        /*
        $grid_onload .= "
            function imageFormat( cellvalue, options, rowObject ){
                return '<img src=\"'+cellvalue+'\" />';
            }
            function imageUnFormat( cellvalue, options, cell){
                return $('img', cell).attr('src');
            }
        ";
        */

        if ($this->_form_edit_enabled) {
            $grid_onload .= $this->_form_edit;
        }

        Controller::appendHeadCodeDynamic($grid_onload);

        return $this;
    }

    function populate()
    {
//TODO перебрать и вязть полезное

        if (!isset($this->grid_options['caption']))
            $this->setGridParam('caption', '');
        if (!isset($this->grid_options['rowNum']))
            $this->setGridParam('rowNum', 10);
        if (!isset($this->grid_options['sortname']))
            $this->setGridParam('sortname', '');
        if (!isset($this->grid_options['hoverrows']))
            $this->setGridParam('hoverrows', true);
        if (!isset($this->grid_options['datatype']))
            $this->setGridParam('datatype', 'json');
        if (!isset($this->grid_options['mtype']))
            $this->setGridParam('mtype', 'GET');
        if (!isset($this->grid_options['rowList']))
            $this->setGridParam('rowList', array(10, 20, 50));
        if (!isset($this->grid_options['gridComplete']))
            $this->setGridParam('gridComplete', 'function(){}');

        if (!isset($this->grid_options['url']))
            $this->setGridParam('url', '');
        if (!isset($this->grid_options['editurl']))
            $this->setGridParam('editurl', PUBLIC_URL);

        if (!isset($this->grid_options['jsonReader']))
            $this->setGridParam('jsonReader', $this->jsonReader);

        #


        #
        if (is_null($this->grid_options))
            $this->setGridConfigOptions();
        ///$this->setGridOptions($this->grid_options);

        #
        if (is_null($this->column_model))
            $this->setGridColModel();
        ///$this->setColModel($this->column_model);

        #
        $this->grid_html = 'dsf';///$this->renderGrid($tbl_id = "#{$this->grid_name}_grid", $pgr_id = "#{$this->grid_name}_pager", $auto_script = true, $summary = null, $params = null, $auto_create_tbl = false, $auto_create_pgr = false, $echo_grid = false);
    }

}